package de.tum.in.eist.im.client;


import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import de.tum.in.eist.im.client.domain.Message;
import de.tum.in.eist.im.client.domain.NewMessagesChunk;
import de.tum.in.eist.im.client.domain.User;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class EIST_IM implements EntryPoint {
private DockLayoutPanel mainPanel = new DockLayoutPanel(Unit.PX);
private TabLayoutPanel centerPanel = new TabLayoutPanel(33, Unit.PX);
private ScrollPanel chatScrollPanel = new ScrollPanel();
private ScrollPanel userScrollPanel = new ScrollPanel();
private FlexTable chatFlexTable = new FlexTable();
private FlexTable userFlexTable = new FlexTable();
private HorizontalPanel titlePanel = new HorizontalPanel();
private VerticalPanel chatPanel = new VerticalPanel();
private VerticalPanel centerChatPanel = new VerticalPanel();
private HorizontalPanel centerChatMsgPanel = new HorizontalPanel();
private TextBox centerChatMsgBox = new TextBox();
private Button centerChatMsgButton = new Button("Send");
private FlexTable loginLoginPanel = new FlexTable();
private FlexTable loginSignupPanel = new FlexTable();
private HorizontalPanel centerRoomIconBar = new HorizontalPanel();
private TextBox lusername = new TextBox();
private TextBox susername = new TextBox();
private PasswordTextBox lpasswd = new PasswordTextBox();
private PasswordTextBox spasswd = new PasswordTextBox();
private PasswordTextBox spasswdrpt = new PasswordTextBox();
private HTML sbutton = new HTML("<img src=\"SignUp.png\">Signup!");
private HTML lbutton = new HTML("<img src=\"login.png\">Login!");
private HTML createRoomButton = new HTML("<img src=\"createRoom.png\" > Create a new room");
private Button enterRoomButton = new Button("Enter default room"); 
private HTML leaveRoomButton = new HTML("<img src=\"back.png\"> leave room");
private HorizontalPanel centerChatIconBar = new HorizontalPanel();
private HTML backtoChatButton = new HTML("<img src=\"back.png\"> go back");
private HTML userListButton = new HTML("<div id=\"button\"><img src=\"user.png\"> Display users</div>");
private HTML getHistoryButton = new HTML("<div id=\"button\"><img src=\"history.png\"> Get history</div>");
private HorizontalPanel roomFinder = new HorizontalPanel();
private FlexTable roomList = new FlexTable();
private HTML about = new HTML("<h1>EIST Instant Messenger</h1><h2>By: <br>Elisabeth Eichholz<br>Benedikt Gruber<br>Michael K&ouml;pferl<br>Hoda Naguib<br>Magdalena Zehetmaier</h2><h2>This Instant Messenger was created in a project during the lecture Introduction to Software Engineering at the Technical University Munich. ");
private ChatServiceBetaAsync server = (ChatServiceBetaAsync) GWT.create(ChatServiceBeta.class);
private User user;
private boolean loggedin = false;
private long usertimestamp = 0;
private TextBox enterRoomName = new TextBox();
private HTML logout = new HTML();
private Timer getMessagesTimer = new Timer() {

	@Override
	public void run() {
		// checks for new messages regularly
		if(loggedin==true)
		{
			getMessages();
		}
	}
	
};

	@Override
	public void onModuleLoad() {
		//Title
		titlePanel.setTitle("EIST Instant Messenger");
		//Main Panel title bar
		mainPanel.addNorth(new HTML("<h1>EIST Instant Messenger</h1>"),42);
		//Login panel
		loginLoginPanel.setText(0,0,"Username");
		loginLoginPanel.setWidget(0,1,lusername);
		loginLoginPanel.setText(1,0,"Password");
		loginLoginPanel.setWidget(1,1,lpasswd);
		lpasswd.addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				if(event.getCharCode() == KeyCodes.KEY_ENTER) {
					login(lusername.getText(),lpasswd.getText());
				}
			}
		});
		loginLoginPanel.setWidget(2, 0, lbutton);
		lbutton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				login(lusername.getText(),lpasswd.getText());
			}
		});
		leaveRoomButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				leaveRoom();
			}
		});
		
		
		//Signup panel
		loginSignupPanel.setText(0,0,"Pick a username");
		loginSignupPanel.setWidget(0,1,susername);
		loginSignupPanel.setText(1,0,"Choose a password");
		loginSignupPanel.setWidget(1,1,spasswd);
		loginSignupPanel.setText(2,0,"Repeat the password");
		loginSignupPanel.setWidget(2,1,spasswdrpt);
		spasswdrpt.addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				if(event.getCharCode() == KeyCodes.KEY_ENTER) {
					signup(susername.getText(),spasswd.getText(),spasswdrpt.getText());
				}
			}
		});
		loginSignupPanel.setWidget(3, 0, sbutton);
		sbutton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				signup(susername.getText(),spasswd.getText(),spasswdrpt.getText());
			}
		});
        
        createRoomButton.addClickHandler(new ClickHandler() {          //new handler for cbutton(create a new room)
			public void onClick(ClickEvent event) {
				createRoom();
			}
		});
        enterRoomButton.addClickHandler(new ClickHandler() {          //new handler for ebutton(enter a room)
			public void onClick(ClickEvent event) {
				enterRoom("default");
			}
		});
        leaveRoomButton.addClickHandler(new ClickHandler() {          //new handler for leaveButton (leave current room)
			public void onClick(ClickEvent event) {
				leaveRoom();
			}
		});
		resetUI();
		
		userListButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				displayUserList();
			}
		});
		getHistoryButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				getHistory();
			}
		});
		centerChatPanel.add(centerRoomIconBar);
		chatScrollPanel.setPixelSize(480,500);
		chatScrollPanel.add(chatFlexTable);
		centerChatPanel.add(chatScrollPanel);
		centerChatPanel.add(centerChatMsgPanel);
		centerChatMsgBox.setVisible(true);
		centerChatMsgPanel.add(centerChatMsgBox);
		centerChatMsgPanel.add(centerChatMsgButton);
		ClickHandler centerChatMsg = new ClickHandler() {
			public void onClick(ClickEvent event) {
				Date d = new Date();
				String t = new String(centerChatMsgBox.getText());
				Message m = new Message(d.getTime(),t,user);
				sendMessage(m);
			}
		};
		centerChatMsgButton.addClickHandler(centerChatMsg);
		centerChatMsgBox.addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				if(event.getCharCode() == KeyCodes.KEY_ENTER) {
					Date d = new Date();
					String t = new String(centerChatMsgBox.getText());
					Message m = new Message(d.getTime(),t,user);
					sendMessage(m);
				}
			}
		});
		mainPanel.add(centerPanel);
		
		RootLayoutPanel.get().add(mainPanel);
		//RootPanel.get("chat").add(centerPanel);
		
	}
	/**
	 * User pressed send button in chat
	 */
	protected void sendMessage(Message m) {
		if(!m.getText().equals(""))
		{
			centerChatMsgBox.setReadOnly(true);
			server.sendMessage(m, new AsyncCallback<Void>() {
				@Override
				public void onFailure(Throwable gotcha) {
					Window.alert("Error sending message");
				}
				@Override
				public void onSuccess(Void result) {
					centerChatMsgBox.setText("");
				}
			});
			centerChatMsgBox.setReadOnly(false);
			centerChatMsgBox.setFocus(true);
		}
		
	}
	/**
	 * User pressed displayUserList button
	 */
	protected void displayUserList() {
		// display the user list instead of the chat panel
		getMessagesTimer.cancel();
		chatPanel.clear();
		centerChatIconBar.clear();
		centerChatIconBar.add(backtoChatButton);
		backtoChatButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				endDisplayUserList();
			}
		});
		chatPanel.add(centerChatIconBar);
		chatPanel.add(userScrollPanel);
		userScrollPanel.setPixelSize(480,500);
		userScrollPanel.add(userFlexTable);
		userFlexTable.removeAllRows();    
		server.getLoggedInUsers( new AsyncCallback<List<User>>() {
			public void onFailure (Throwable gotcha)
			{
				Window.alert("Found an error: "+gotcha.getMessage());
			}
			public void onSuccess (List<User> result)
			{
				int i=result.size()-1;
				while(i>-1) {
					userFlexTable.insertRow(0); 
					userFlexTable.setText(0,0,result.get(i).getUsername());
					i--;
				}
			}
		});
		// draw user interface
		
	}
	/**
	 * user pressed getHistory button
	 */
	protected void getHistory() {
		// load the history into the active chat window
		// not implemented into the basic functionality
		Window.alert("Pretending to load chat history...");
		
	}
	/**
	 * User pressed "back" in user list
	 */
	protected void endDisplayUserList() {
		// display the chat panel again
		chatPanel.clear();
		centerChatIconBar.remove(backtoChatButton);
		centerChatIconBar.add(leaveRoomButton);
		centerChatIconBar.add(userListButton);
		centerChatIconBar.add(getHistoryButton);
		chatPanel.add(centerChatIconBar);
		chatPanel.add(centerChatPanel);
		chatScrollPanel.scrollToBottom();
		getMessagesTimer.scheduleRepeating(100);
	}
	/**
	 * user pressed signup button
	 */
	protected void signup(final String username, final String password, final String password2) {
		if(!password.equals(password2)) {
			Window.alert("passwords are not the same");
			return;
		}
		user = new User(username, password);
		AsyncCallback<Void> callback = new AsyncCallback<Void>() {
			public void onFailure (Throwable gotcha)
			{
				Window.alert("Found an error: "+gotcha.getMessage());
			}
			public void onSuccess (Void result)
			{
				login(username,password);
			}
		};
		//server.registerNewUser(user, callback);
		// stub

	      Window.alert("in signup");
	      //centerPanel.selectTab(loginLoginPanel);
	      // call login to login the newly created user
	      login(username,password);
	}

	/**
	 * User pressed login button
	 */
	public boolean login(String username, String password) {
		// TODO Check for correct given login information
		// not possible with alpha server, because it always logs the user in
		user = new User(username, password);
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onFailure(Throwable gotcha)
			{
				Window.alert("Found an error: "+gotcha.getMessage());
			}
			public void onSuccess (Boolean result)
			{
				if(result==true) {
					loggedin=result;
					// redraw window
						centerPanel.clear();
						logout.setVisible(true);
						logout.setHTML("<img src=\"logout.png\"> Logout "+user.getUsername());
						centerPanel.add(new HTML(""),logout);
						logout.addClickHandler(new ClickHandler() {
							public void onClick(ClickEvent event) {
								logout();
							}
						});
						// just to make sure ;-)
						leaveRoom();
					// fill GUI with content
				} else {
					Window.alert("Error logging you into the server");
					logout.setVisible(false);
				}
			}
		};
		server.login(user,callback);
return logout.isVisible();

	}
	/**
	 * User pressed logout button
	 */
	protected void logout(){
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onFailure(Throwable gotcha)
			{
				Window.alert("Found an error: "+gotcha.getMessage());
			}
			public void onSuccess (Boolean result)
			{
				if(result==true) {
					loggedin=!result;
					resetUI();
					logout.setVisible(false);
				} else {
					Window.alert("Error logging you out of the server");
					logout.setVisible(true);
				}
			}
		};
		server.logout(user,callback);
	}
	/**
	 * resets the user interface
	 */
	protected void resetUI() {
		centerPanel.clear();
		centerPanel.add(loginSignupPanel,new HTML("<img src=\"user.png\"> Sign Up"));
		centerPanel.add(loginLoginPanel,new HTML("<img src=\"login.png\"> Login"));
		centerPanel.add(about,"About");
		centerPanel.selectTab(loginLoginPanel);
		getMessagesTimer.cancel();
	}
	/**
	 * user created a new room
	 */
	protected void createRoom(){
		//TODO Add create room functionality
		// for beta, not implemented in alpha
		String roomName = enterRoomName.getText();
		//just to make sure ;-)
		enterRoom(roomName);
	}
	/**
	 * user selected a room to enter
	 */
	protected void enterRoom(String s) {
		// TODO enter a channel
		// not part of alpha version
		// draw user interface
		if(!s.equals("default")) chatFlexTable.removeAllRows();
		centerPanel.remove(roomFinder);
		centerPanel.add(chatPanel,"Chat");
		centerPanel.selectTab(chatPanel);
		chatPanel.add(centerChatPanel);
		//just to make sure ;-)
		endDisplayUserList();
	}
	/** 
	 * this function gets new Messages from the Server
	 */
	protected void getMessages() {
		server.getNewMessages(usertimestamp, new AsyncCallback<NewMessagesChunk>() {
			public void onSuccess (NewMessagesChunk chunk) {
				usertimestamp=chunk.getTimestamp();
				List<Message> ml = chunk.getMessages();
				for(int i=ml.size()-1;i>-1;i--) {
					Message m=ml.get(i);
					chatFlexTable.setText(chatFlexTable.getRowCount(), 0, m.getSender().getUsername());
					//chatFlexTable.setText(chatFlexTable.getRowCount(), 1, new String(""+m.getTimestamp()));
					chatFlexTable.setText(chatFlexTable.getRowCount(), 2, m.getText());
					chatScrollPanel.scrollToBottom();
					chatScrollPanel.scrollToLeft();
				}
			}
			public void onFailure(Throwable gotcha) {
				//Inform the user about the error
				Window.alert("Error: "+gotcha.getMessage());
			}
		});
	}
	/**
	 * User pressed leave room button
	 */
	protected void leaveRoom(){
		centerPanel.remove(chatPanel);
		centerPanel.add(roomFinder, new HTML("Select Room"));
        centerRoomIconBar.add(enterRoomButton);
        centerRoomIconBar.add(enterRoomName);
        centerRoomIconBar.add(createRoomButton);
		roomFinder.add(centerRoomIconBar);
		roomFinder.add(roomList);
		centerPanel.selectTab(roomFinder);
		getMessagesTimer.cancel();
	}
}
